<?php

namespace app\cms\service\jd;

use app\cms\service\jd\stub\GoodsResp;
use app\cms\service\jd\stub\PromotionCodeResp;
use JdClient;

class JdClientWrapper
{
    /**
     * @var JdClientWrapper
     */
    private static $_instance;

    /**
     * @var JdClient
     */
    private $jdClient;

    private function __construct(JdClient $client){
        $this->jdClient = $client;
    }

    /**
     * @return JdClientWrapper
     */
    public static function inst() {
        if (static::$_instance == null) {
            require_once __DIR__. DS. 'init_jd_client_script.php';

            $c = new JdClient();
            $c->appKey = "990c86607abf45be96d24dc5ba56936c";
            $c->appSecret = "a38371436b844abfa7adc61acc3b012b";
            $c->accessToken = "1f1d3048-220a-484d-ad93-f3808d9aacc1";
            $c->serverUrl = "https://api.jd.com/routerjson";

            return static::$_instance = new JdClientWrapper($c);
        }
        return static::$_instance;
    }


    /**
     * 按关键词查找商品
     *
     * 参数字段参考：
     * @link https://union.jd.com/openplatform/api/v2?apiName=jd.union.open.goods.query
     * @param String $keyword 商品关键词
     * @param int $page
     * @param int $pageSize
     * @return array|GoodsResp[]
     */
    public function queryByKeyword(string $keyword, int $page = 1, int $pageSize = 20): array
    {
        $req = new \UnionOpenGoodsQueryRequest();

        $dto = [
            'keyword' => $keyword,
            'isCoupon' => 1,
            'pageIndex' => $page > 0 ? $page : 1,
            'pageSize' => ($pageSize > 0 && $pageSize <= 30) ? $pageSize : 20,
        ];

        $req->setGoodsReqDTO($dto);

        $result = $this->jdClient->execute($req);
        return $this->checkAndGetResult($result, 'jd_union_open_goods_query_responce');
    }


    /**
     * 获取推广链接。
     *
     * 参数字段参考：
     * @link https://union.jd.com/openplatform/api/v2?apiName=jd.union.open.promotion.common.get
     *
     * @param String $materialUrl 物料url，既商品url
     * @param String $couponUrl 优惠券url
     * @return object|PromotionCodeResp
     */
    public function convertClickUrl(String $materialUrl, String $couponUrl) : object {
        $req = new \UnionOpenPromotionCommonGetRequest();

        $dto = [
            'materialUrl' => $materialUrl,
            'couponUrl' => $couponUrl,
        ];

        $req->setPromotionCodeReq($dto);
        $result = $this->jdClient->execute($req);
        return $this->checkAndGetResult($result, 'jd_union_open_promotion_common_get_response');
    }


    private function checkAndGetResult($resp, $entryName) {

        $response = $resp->$entryName;
        if (empty($response)) {
            throw new \RuntimeException("Invalid response. Can not find root node as $entryName. Response: \n".
                json_encode($resp, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        }

        if ($response->code != 0) {
            throw new \RuntimeException("Unsuccessful response. Response: \n".
                json_encode($resp, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        }

        $result = null;
        if ($response->queryResult != null) {
            $result = json_decode($response->queryResult);
        } else if ($response->getResult != null) {
            $result = json_decode($response->getResult);
        }

        if (empty($result) && is_object($result)) {
            throw new \RuntimeException("Invalid result json. Resp: ". json_encode($resp, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        }

        if ($result->code != 200 || $result->message != 'success') {
            throw new \RuntimeException("Remote error: [{$result->code}] {$result->message}. RequestId: {$result->requestId}");
        }

        return $resp->data;
    }
}